#ifndef _Format_
#define _Format_

#include<iostream>
#include<memory>
#include"message.hpp"
#include"level.hpp"
#include"util.hpp"
#include<vector>
#include<cassert>
#include<sstream>
namespace log
{
    class FormatItem{
        public: 
        using ptr = std::shared_ptr<FormatItem>;
        virtual void format(std::ostream &out,const LogMsg &msg)= 0;

    };
    //派生格式化子项子类--消息，日志等级，文件名，线程id，日期，缩进，行号 换行，日志器名称

    class MsgFormatItem : public FormatItem{
        public:
        void format(std::ostream &out,const LogMsg &msg) override //重写关键字，没实现重写会报错
        {
            out<<msg._payload;
        }

    };

    class LevelFormatItem : public FormatItem {
        public:
        void format(std::ostream &os, const LogMsg &msg) override
        {
            os<<LogLevel::ToSring(msg._level);
        }

    };


    class FileFormatItem : public FormatItem{
        public:
        void format(std::ostream &out, const LogMsg &msg) override
        {
            out<<msg._file;
        }

    };

    class TimeFormatItem : public FormatItem{
        public:
        TimeFormatItem(const std::string &fmt = "%H:%M:%S"):_time_fmt(fmt){} //"%H:%M:%S" 
        void format(std::ostream &out, const LogMsg &msg) override
        {
            struct tm t;
            localtime_r(&msg._ctime, &t);//获取系统本地时间
            char tmp[32] = {0};
            strftime(tmp, 31, _time_fmt.c_str(), &t);//格式化输出时分秒到tmp数组
            out<<tmp;

        }
        private:
        std::string _time_fmt;//时间格式化字符串
    };
    
    class LineFormatItem : public FormatItem{
        public:
        void format(std::ostream &out, const LogMsg &msg) override
        {
            out<<msg._line;
        }
    };
    
    class ThreadFormatItem : public FormatItem{
        public:
        void format(std::ostream &out, const LogMsg &msg) override
        {
            out<<msg._tid;
        }
    };
    class LoggerFormatItem : public FormatItem{
        public:
        void format(std::ostream &out, const LogMsg &msg) override
        {
            out<<msg._logger;
        }
    };

    class TabFormatItem : public FormatItem{
        void format(std::ostream &out, const LogMsg &msg) override
        {
            out<<"\t";
        }
    };

    class NlineFormatItem : public FormatItem{
        public:
        void format(std::ostream &out, const LogMsg &msg ) override
        {
            out<<"\n";
        }
    };
    
    class OtherFormatItem : public FormatItem{
        public:
        OtherFormatItem(const std::string &str):_str(str){}
        void format(std::ostream &out, const LogMsg &msg) override
        {
            out<<_str;
        }

        private:
        std::string _str;
    };


            // %d 日期
            // %T 缩进
            // %t 线程id
            // %p 日志级别
            // %c 日志器名称
            // %f 文件名
            // %l 行号
            // %m 日志消息
            // %n 换行


    class Formatter{
        public:
        using ptr = std::shared_ptr<Formatter>;
       Formatter(const std::string &pattern ="[%d{%H:%M:%S}][%t][%c][%f:%l][%p]%T%m%n" )
       :_pattern(pattern)
       {
         assert(parsePattern());
       }

        //格式化输出字符串
        void format(std::ostream &out,LogMsg &msg)
        {
            for(auto &item : _items)
            {
                item->format(out,msg);
            }
        }
        
        std::string format(LogMsg &msg)
        {
            std::stringstream ss;
            format(ss,msg);
            return ss.str();
        }

        private:

        //对格式化规则字符串进行解析
        bool parsePattern()
        { //abc%%[%d{%H:%M:%S}][%t][%c][%f:%l][%p]%T%m%n
            std::vector<std::pair<std::string, std::string>> fmt_order;
            size_t pos = 0;
            std::string key, val;
            while(pos < _pattern.size())
            {
                //处理原始字符串--判断是否是%， 不是就是原始字符
                if(_pattern[pos] !='%')
                {
                    val.push_back(_pattern[pos++]);
                    continue;
                }
                //能走下来就代表pos位置就是%字符， %%处理成为一个原始%字符
                if(_pattern[pos+1]=='%' && pos+1 < _pattern.size())
                {
                    val.push_back('%');
                    pos += 2; 
                    continue;
                }
                //能走下来，代表%后边是个格式化字符，代表原始字符处理完毕
                if(val.empty() == false)
                {
                    fmt_order.push_back(std::make_pair("",val));
                    val.clear();
                }

                //这时候指向的是%位置， 是格式化字符的处理
                pos += 1;//这一步之后。pos指向格式化字符的位置
                if(pos == _pattern.size())
                {
                    std::cout<<"%之后，没有对应的格式化字符！\n";
                    return false;
                }
                 key = _pattern[pos];
                 pos += 1; //这时候pos指向子规则的起始位置
                if(pos < _pattern.size() && _pattern[pos] == '{')
                {
                       
                   while(pos < _pattern.size() && _pattern[pos]!='}')
                   {
                      val.push_back(_pattern[pos++]);
                   }

                   if(pos == _pattern.size())
                    {
                      std::cout << "子规则{}匹配错误!\n";
                      return false; //没有找到}
                    }
                   pos += 1; //因为这时候pos指向的是}位置，向后走一步，走到下次处理的新位置
                } 
                
                fmt_order.push_back(std::make_pair(key,val));
                key.clear();
                val.clear();
            
            }
              
                for(auto &it : fmt_order)
                {
                    _items.push_back(createItem(it.first, it.second));
                }
                return true;
            

        }

        //根据不同的格式化字符创建不同的格式化子项对象
        FormatItem::ptr createItem(const std::string &key, const std::string &val)
        {
            if(key=="d") return std::make_shared<TimeFormatItem>(val);
            if(key=="t") return std::make_shared<ThreadFormatItem>();
            if(key=="c") return std::make_shared<LoggerFormatItem>();
            if(key=="f") return std::make_shared<FileFormatItem>();
            if(key=="l") return std::make_shared<LineFormatItem>();
            if(key=="p") return std::make_shared<LevelFormatItem>();
            if(key=="T") return std::make_shared<TabFormatItem>();
            if(key=="m") return std::make_shared<MsgFormatItem>();
            if(key=="n") return std::make_shared<NlineFormatItem>();     
            if(key=="" ) return std::make_shared<OtherFormatItem>(val);
            std::cout << "没有对应的格式化字符：%"<<key<< std::endl;
            abort();
            return FormatItem::ptr(); 
        }
        std::string _pattern; //格式化规则字符串
        std::vector<FormatItem::ptr> _items;//格式化子项对象数组
    };

}




#endif 